package cn.com.cifi.mars.service.impl;

import cn.com.cifi.mars.bean.dto.OrgDataDto;
import cn.com.cifi.mars.bean.dto.SysProcessConfigDto;
import cn.com.cifi.mars.bean.vo.sys.req.SaveSysProcessConfigReqParam;
import cn.com.cifi.mars.bean.vo.sys.req.UpdateSysProcessConfigReqParam;
import cn.com.cifi.mars.bean.vo.sys.rsp.SysProcessConfigVo;
import cn.com.cifi.mars.common.exception.MsgException;
import cn.com.cifi.mars.constant.CodeEnum;
import cn.com.cifi.mars.constant.Constants;
import cn.com.cifi.mars.constant.HrOrgTypeEunm;
import cn.com.cifi.mars.entity.common.SysDictionary;
import cn.com.cifi.mars.entity.common.SysProcessConfig;
import cn.com.cifi.mars.mapper.mars.IdmOrgMapper;
import cn.com.cifi.mars.mapper.mars.SysDictionaryMapper;
import cn.com.cifi.mars.mapper.mars.SysProcessConfigMapper;
import cn.com.cifi.mars.service.SysProcessConfigService;
import cn.com.cifi.mars.util.DateUtils;
import cn.com.cifi.mars.util.UUIDUtils;
import lombok.extern.slf4j.Slf4j;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import java.io.IOException;
import java.io.InputStream;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author yyd
 * @since 2019-09-21
 */
@Slf4j
@Service
public class SysProcessConfigServiceImpl extends ServiceImpl<SysProcessConfigMapper, SysProcessConfig> implements SysProcessConfigService {

	@Autowired
	private SysProcessConfigMapper sysProcessConfigMapper;
	@Autowired
	private SysDictionaryMapper sysDictionaryMapper;
	@Autowired
	private IdmOrgMapper orgMapper;
	
	private static final String TYPE_ID = "type_id"; 
	
	private static final String REGION_ID = "region_id"; 
	
	private static final String TYPE_CODE="type_code";
	
	private static final String DICT_VALUE="dict_value";
	
	private static final String DICT_NAME="dict_name";

	/**
	 * 添加
	 */
	@Transactional(rollbackFor = Exception.class)
	@Override
	public int add(SaveSysProcessConfigReqParam param, String name) {
		//判断区域和类型是否存在
		QueryWrapper<SysProcessConfig>queryWrapper=new QueryWrapper<>();
		queryWrapper.eq(TYPE_ID, param.getTypeId());
		queryWrapper.eq(REGION_ID, param.getRegionId());
		SysProcessConfig sys=sysProcessConfigMapper.selectOne(queryWrapper);
		if(sys!=null) {
			throw new MsgException(CodeEnum.SYS_PROCESS_ERROR);
		}
		
		//获取区域是否存在
		OrgDataDto orgDataDto=orgMapper.selectByOrgId(param.getRegionId());
		if(null==orgDataDto) {
			throw new MsgException(CodeEnum.SYS_REGION_ID_ERROR);
		}
		//获取类型是否存在
		QueryWrapper<SysDictionary> qw=new QueryWrapper<>();
		qw.eq(TYPE_CODE, Constants.PROCESS_TYPE);
		qw.eq(DICT_VALUE, param.getTypeId());
		SysDictionary sysDictionary=sysDictionaryMapper.selectOne(qw);
		if(null==sysDictionary) {
			throw new MsgException(CodeEnum.SYS_PRO_TYPE_ID_ERROR);
		}
		
		SysProcessConfig bean=new SysProcessConfig();
		BeanUtils.copyProperties(param, bean);
		bean.setCreateby(name);
		bean.setCreateTime(LocalDateTime.now());
		bean.setId(UUIDUtils.create());
		bean.setRegionName(orgDataDto.getOrgname());
		bean.setTypeName(sysDictionary.getDictName());
		return sysProcessConfigMapper.insert(bean);
	}

	/**
	 * 编辑
	 */
	@Transactional(rollbackFor = Exception.class)
	@Override
	public int update(UpdateSysProcessConfigReqParam param, String name) {
		SysProcessConfig bean = sysProcessConfigMapper.selectById(param.getId());
		if(null==bean) {
			throw new MsgException(CodeEnum.SYS_PROCESS_ID_ERROR);
		}
		//判断区域和类型是否存在
		QueryWrapper<SysProcessConfig>queryWrapper=new QueryWrapper<>();
		queryWrapper.eq(TYPE_ID, param.getTypeId());
		queryWrapper.eq(REGION_ID, param.getRegionId());
		List<SysProcessConfig> sysList = sysProcessConfigMapper.selectList(queryWrapper);
		if (!CollectionUtils.isEmpty(sysList)) {
			if(isExist(bean, param)) {
				throw new MsgException(CodeEnum.SYS_PROCESS_ERROR);
			}
		}
		
		//获取区域是否存在
		OrgDataDto orgDataDto=orgMapper.selectByOrgId(param.getRegionId());
		if(null==orgDataDto) {
			throw new MsgException(CodeEnum.SYS_REGION_ID_ERROR);
		}
		//获取类型是否存在
		QueryWrapper<SysDictionary> qw=new QueryWrapper<>();
		qw.eq(TYPE_CODE, Constants.PROCESS_TYPE);
		qw.eq(DICT_VALUE, param.getTypeId());
		SysDictionary sysDictionary=sysDictionaryMapper.selectOne(qw);
		if(null==sysDictionary) {
			throw new MsgException(CodeEnum.SYS_PRO_TYPE_ID_ERROR);
		}
		
		BeanUtils.copyProperties(param, bean);
		bean.setCreateby(name);
		bean.setRegionName(orgDataDto.getOrgname());
		bean.setTypeName(sysDictionary.getDictName());
		return sysProcessConfigMapper.updateById(bean);
	}

	/**
	 *     是否存在
	 * @param bean
	 * @param param
	 * @return
	 */
	private static boolean isExist(SysProcessConfig bean,UpdateSysProcessConfigReqParam param) {
		return !bean.getTypeId().equals(param.getTypeId()) && bean.getRegionId().equals(param.getRegionId());
	}
	
	/**
	 * 删除
	 */
	@Transactional(rollbackFor = Exception.class)
	@Override
	public int delete(String id) {
		return sysProcessConfigMapper.deleteById(id);
	}

	/**
	 * 流程配置分页
	 */
	@Override
	public SysProcessConfigVo querySysProcessConfigPage(String current, String pageSize,String regionId) {
		SysProcessConfigVo vo=new SysProcessConfigVo();
		Page<SysProcessConfigDto>pageDto=new Page<>();
		//参数当前页
		pageDto.setCurrent(Integer.parseInt(current));
		//参数每页数量
		pageDto.setSize(Integer.parseInt(pageSize));
		List<SysProcessConfigDto>list= sysProcessConfigMapper.selectSysProcessConfig(pageDto,regionId);
		vo.setCurrent(pageDto.getCurrent());
		vo.setPages(pageDto.getPages());
		vo.setPageSize(pageDto.getSize());
		vo.setTotal(pageDto.getTotal());
		vo.setList(list);
		return vo;
	}

	/**
	 * 查询列表信息
	 */
	@Override
	public List<SysProcessConfigDto> queryProcessConfigList(String regionId) {
		List<SysProcessConfigDto>dtoList=new ArrayList<>();
		QueryWrapper<SysProcessConfig>queryWrapper=new QueryWrapper<>();
		if(StringUtils.isNotBlank(regionId)) {
			queryWrapper.eq(REGION_ID, regionId);
		}
		List<SysProcessConfig>list=sysProcessConfigMapper.selectList(queryWrapper);
		list.forEach(x->{
			SysProcessConfigDto dto=new SysProcessConfigDto();
			BeanUtils.copyProperties(x, dto);
			dto.setCreateStr(DateUtils.formatString(x.getCreateTime()));
			dtoList.add(dto);
		});
		return dtoList;
	}

	/**
	 * 导入流程配置
	 */
	@Transactional(rollbackFor = Exception.class)
	@Override
	public String importSysProcessConfig(MultipartFile file,String name) {
		boolean flag=excelImport(file,name);
		return flag ? "导入成功":"导入失败";
	}
	
	/**
	 * 获取字典code
	 * @param dictName
	 * @param typeCode
	 * @return
	 */
	public String getDictCode(String dictName,String typeCode) {
		QueryWrapper<SysDictionary>queryWrapper=new QueryWrapper<>();
		queryWrapper.eq(TYPE_CODE, typeCode);
		queryWrapper.eq(DICT_NAME, dictName);
		SysDictionary sd=sysDictionaryMapper.selectOne(queryWrapper);
		if(sd!=null) {
			return sd.getDictCode();
		}
		return "";
	}
	
	/**
	 * 导入流程配置
	 */
	@Transactional(rollbackFor = Exception.class)
	public boolean excelImport(MultipartFile file,String name) {
		//判断Excel文件是否有内容
		boolean notNull=false;
		String filename=file.getOriginalFilename();
		String key="^.+\\.(?i)(xls)$";
		String key1="^.+\\.(?i)(xlsx)$";
		if (!filename.matches(key) && !filename.matches(key1)) {
            try {
				throw new Exception("上传文件格式不正确");
			} catch (Exception e) {
				log.error(e.getMessage());
			}
        }
		//判断Excel文件的版本
		boolean isExcel2003=true;
	    if (filename.matches(key1)) {
            isExcel2003 = false;
        }
	    InputStream resouce=null;
		try {
			resouce = file.getResource().getInputStream();
		} catch (IOException e1) {
			log.error(e1.getMessage());
		}
	    InputStream is=resouce;
	    Workbook wb=null;	    
	    if (isExcel2003) {
            try {
				wb = new HSSFWorkbook(is);
			} catch (IOException e) {
				log.error(e.getMessage());
			}
        } else {
            try {
				wb = new XSSFWorkbook(is);
			} catch (IOException e) {
				log.error(e.getMessage());
			}
        }
  		
  		//获取Excel文件的第一页sheet，判断是否有信息
	    Sheet sheet=wb.getSheetAt(0);
	    if(sheet!=null){
	    	notNull=true;
	    }
	    
	    List<String> valuesList=new ArrayList<>();
	    //获取行数，第一行是标题
	    //遍历Excel文件
	    int totalRows = sheet.getPhysicalNumberOfRows();	
	    Row row=null;
	    int totalCells=0;	
	    for (int i = 1; i < totalRows; i++) {
	    	valuesList.clear();
	    	//遍历单元格
	    	row=sheet.getRow(i);
	    	//获取每一行的单元格数
	    	totalCells= row.getPhysicalNumberOfCells();		
	    	//循环设置每个单元格的数据类型为String类型
	    	for (int j = 0; j < totalCells; j++) {
	    		if(row.getCell(j)!=null){
			          row.getCell(j).setCellType(Cell.CELL_TYPE_STRING);
			    }
			}
	    	
	    	//获取每个单元格的数据，保存到集合中
	    	for (int t = 0; t < totalCells; t++) {	    		
	    		//判断单元格类型是否为空
	    		if(null==row.getCell(t, row.RETURN_BLANK_AS_NULL)){
	    			Cell cell=row.createCell(t); 	    			
	    			cell.setCellValue("");
	    		}
	    		String cellInfo=row.getCell(t).getStringCellValue();
	    		//判断单元格内容是否为空
	    		if(StringUtils.isBlank(cellInfo)){
	    			cellInfo="";
	    		}	    		
	    		//再判断是数字类型还是字符类型还是空类型
	    		if(isNumber(cellInfo) || cellInfo.equals("NULL")){
	 	    		valuesList.add(cellInfo);
	 	    	}else{
	 	    		valuesList.add("\""+cellInfo+"\"");
	 	    	}			
			}
	    	//如果参数存在禁止导入,不存在添加
			//区域名称 类型名称	流程key	流程说明		
			String regionName=valuesList.get(0).replaceAll("\"", "");
			if(!StringUtils.isNotBlank(regionName)) {
				CodeEnum.SYS_ERROR.setMessage("第"+i+"行数据为空,请清空后再上传");
				throw new MsgException(CodeEnum.SYS_ERROR);
			}
			String typeName=valuesList.get(1).replaceAll("\"", "");
			String keyId=valuesList.get(2).replaceAll("\"", "");
			String proDesc=valuesList.get(3).replaceAll("\"", "");
			
			if(!StringUtils.isNotBlank(regionName)) {
				throw new MsgException(CodeEnum.SYS_REGION_ID_ERROR);
			}
			if(!StringUtils.isNotBlank(typeName)) {
				throw new MsgException(CodeEnum.SYS_PRO_TYPE_ID_ERROR);
			}
			//根据类型名称和类型code获取类型id
			String typeId=getDictCode(typeName,Constants.PROCESS_TYPE);
			//根据区域名称获取区域id
			String regionId=orgMapper.selectByOrgNameAndHrOrgTypeId(Constants.ORGSTATUS, HrOrgTypeEunm.ORG_20.getKey(),regionName);
			String cityId=orgMapper.selectByOrgNameAndHrOrgTypeId(Constants.ORGSTATUS, HrOrgTypeEunm.ORG_21.getKey(),regionName);
			
			String qyid="";
			if(StringUtils.isNotBlank(regionId)) {
				qyid=regionId;
			}else if(StringUtils.isNotBlank(cityId)) {
				qyid=cityId;
			}
			if(!StringUtils.isNotBlank(qyid)) {
				throw new MsgException(CodeEnum.SYS_REGION_ID_ERROR);
			}
			if(!StringUtils.isNotBlank(typeId)) {
				throw new MsgException(CodeEnum.SYS_PRO_TYPE_ID_ERROR);
			}
			
			
			//判断区域和类型是否存在
			QueryWrapper<SysProcessConfig>queryWrapper=new QueryWrapper<>();
			queryWrapper.eq(TYPE_ID, typeId);
			queryWrapper.eq(REGION_ID, qyid);
			SysProcessConfig sys=sysProcessConfigMapper.selectOne(queryWrapper);
			if(sys!=null) {
				throw new MsgException(CodeEnum.SYS_PROCESS_ERROR);
			}
			SysProcessConfig bean=new SysProcessConfig();
			bean.setRegionId(qyid);
			bean.setTypeId(typeId);
			bean.setRegionName(regionName);
			bean.setKeyId(keyId);
			bean.setTypeName(typeName);
			bean.setProDesc(proDesc);
			bean.setCreateby(name);
			bean.setCreateTime(LocalDateTime.now());
			bean.setId(UUIDUtils.create());
			sysProcessConfigMapper.insert(bean);
		}
		return notNull;
	}
	
	
	/**
	 * 判断字符串是否为数字
	 * @param str
	 * @return
	 */
	public static boolean isNumber(String str){
		for (int i = 0; i < str.length(); i++) {
			if(!Character.isDigit(str.charAt(i))){
				return false;
			}
		}
		return true;
	}
	
	/**
	 * 流程配置编辑时查询区域层级
	 */
	@Override
	public String getRank(String id) {
		SysProcessConfig bean = sysProcessConfigMapper.selectById(id);
		if(null==bean) {
			throw new MsgException(CodeEnum.SYS_PROCESS_ID_ERROR);
		}
		String regionId=bean.getRegionId();
		OrgDataDto p=orgMapper.selectByIdmOrgId(regionId);
		if(p.getHrOrgTypeId().equals(HrOrgTypeEunm.ORG_20.getKey())) {
			return "区域级";
		}else {
			return "城市公司级";
		}
	}
	
	
}
